﻿//-----------------------------------------------------------------------
// <copyright file="DB.cs" company="Microsoft Corporation">
//     Copyright Microsoft Corporation. All Rights Reserved. This code released under the terms of the Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.) This is sample code only, do not use in production environments.
// </copyright>
//-----------------------------------------------------------------------

namespace Microsoft.ALMRangers.VsarTreasureMap.WindowsStoreApp.Models
{
    using System;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Xml.Linq;
    using Windows.Storage;

    /// <summary>
    ///  Object representation of the database.
    /// </summary>
    public class DB
    {
        /// <summary>
        /// Gets the status manager.
        /// </summary>
        public StatusManager StatusManager { get; private set; }

        /// <summary>
        /// Gets the Categories
        /// </summary>
        public Category[] Categories { get; private set; }

        /// <summary>
        /// Gets the urls to the news feeds
        /// </summary>
        public Uri[] NewsUrls { get; private set; }

        /// <summary>
        /// Initializes the DB from the xml file generating the apps data.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        public async Task LoadDBAsync()
        {
            var dataFileUri = new Uri("ms-appx:///DataProviders/TreasureMapDataModel.xml", UriKind.Absolute);
            var dataFile = await StorageFile.GetFileFromApplicationUriAsync(dataFileUri);
            var rawData = await FileIO.ReadTextAsync(dataFile);
            var xmlDocument = XDocument.Parse(rawData); 

            this.NewsUrls = xmlDocument.Descendants("site").Select(_ =>
                {
                    var uri = default(Uri);
                    if (Uri.TryCreate(_.Attribute("url").Value, UriKind.Absolute, out uri))
                    {
                        return uri;
                    }

                    return null;
                }).Where(_ => _ != null).ToArray();

            var categories = xmlDocument.Descendants("category").ToArray();
            this.Categories = new Category[categories.Length];
            var categoryCounter = 0;
            var uniqueProjectCounter = 0;
            var uniqueGuidanceCounter = 0;
            foreach (var category in categories)
            {
                var newCategory = new Category()
                {
                    Id = Convert.ToInt32(category.Attribute("id").Value),
                    Description = category.Attribute("description").Value,
                    Image = "ms-appx:///" + category.Attribute("image").Value,
                    Name = category.Attribute("name").Value,
                };

                var projects = category.Descendants("project")
                                .OrderBy(_ => Convert.ToInt32(_.Attribute("order").Value))
                                .ToArray();

                newCategory.Projects = new Project[projects.Length];
                var projectCounter = 0;
                foreach (var project in projects)
                {
                    var newProject = new Project()
                    {
                        Category = newCategory.Id,
                        Id = uniqueProjectCounter,
                        Name = project.Attribute("name").Value,
                        Order = Convert.ToInt32(project.Attribute("order").Value),
                        Image = "ms-appx:///" + project.Attribute("image").Value,
                        Description = project.Attribute("description").Value,
                    };

                    var guidances = project.Descendants("guidance")
                        .OrderBy(_ => Convert.ToInt32(_.Attribute("order").Value))
                        .ToArray();

                    newProject.Guidance = new Guidance[guidances.Length];
                    var guidanceCount = 0;
                    foreach (var guidance in guidances)
                    {
                        var newGuidance = new Guidance()
                        {
                            Order = Convert.ToInt32(guidance.Attribute("order").Value),
                            Category = newCategory.Id,
                            CategoryTitle = newCategory.Name,

                            Id = Convert.ToInt32(guidance.Attribute("id").Value),
                            GuidanceType = (MaterialType)Enum.Parse(typeof(MaterialType), guidance.Attribute("type").Value, true),
                            Originator = guidance.Attribute("originator").Value,
                            ProjectId = newProject.Id,
                            ProjectName = newProject.Name,
                            Url = guidance.Attribute("url").Value
                        };

                        newProject.Guidance[guidanceCount] = newGuidance;
                        guidanceCount++;
                        uniqueGuidanceCounter++;
                    }

                    newCategory.Projects[projectCounter] = newProject;
                    projectCounter++;
                    uniqueProjectCounter++;
                }

                this.Categories[categoryCounter] = newCategory;
                categoryCounter++;
            }

            // Do not instantiate the StatusManager class until the Category/Project/Guidance
            // hierarchy has been populated
            StatusManager = new StatusManager(this);
        }
    }
}